/*
 * @Date: 2022-05-23 11:33:44
 * @LastEditors: sailornpg
 * @LastEditTime: 2022-05-23 16:53:04
 * @FilePath: \my-react-components\src\component\Select\index.tsx
 * @Description: Select
 */
import React, {
  createContext,
  memo,
  useRef,
  useState,
  KeyboardEvent,
} from "react";
import classNames from "classnames";
import { OptionProps } from "./Option";
import useClickOutSide from "@/hooks/useClickOutSide";
import Input from "../Input";
import Icon from "../Icon";
export interface SelectProps {
  mode?: "default" | "multiple";
  disabled?: boolean;
  children: React.ReactNode;
  className?: string;
  style?: React.CSSProperties;
  onSelect?: () => void;
}
interface ISContext {
  onSelect?: () => void;
}
export const SelectContext = createContext<ISContext>({});
const Select: React.FC<SelectProps> = memo(
  ({ mode, disabled, children, className, style, ...restProp }) => {
    const [selectChild, setSelectChild] = useState<string>("");
    const [showDrowdown, setShowDrowdown] = useState(false);
    const [highlightIndex, setHighlightIndex] = useState(-1);
    const [selectedOptions, setSelectedOptions] = useState<string[]>([]);
    const componentRef = useRef<HTMLDivElement>(null);
    const classes = classNames("sailor-select-wrapper", className, {
      "is-show": showDrowdown,
    });
    useClickOutSide(componentRef, () => {
      if (showDrowdown) {
        setShowDrowdown(!showDrowdown);
      }
    });
    const highlight = (index: number) => {
      if (index < 0) index = 0;
      if (index >= (children as Array<any>).length) {
        index = (children as Array<any>).length - 1;
      }
      setHighlightIndex(index);
    };
    const keyDown = (e: KeyboardEvent<HTMLInputElement>) => {
      switch (e.key) {
        case "ArrowUp":
          highlight(highlightIndex - 1);
          break;
        case "ArrowDown":
          highlight(highlightIndex + 1);
          break;
        default:
          break;
      }
    };

    const renderChildren = () => {
      return React.Children.map(children, (child, index) => {
        const childrenEl = child as React.FunctionComponentElement<OptionProps>;
        const { displayName } = childrenEl.type;
        if (displayName === "Option") {
          const classnames = classNames("suggestion-item", {
            "is-active": index === highlightIndex,
          });
          return (
            <li
              className={classnames}
              key={index}
              onClick={(e) => {
                if (mode !== "multiple") {
                  setSelectChild(childrenEl.props.children! as string);
                } else {
                  const arr: string[] = [...selectedOptions];
                  arr.push(childrenEl.props.children! as string);
                  setSelectedOptions(arr);
                }
                setShowDrowdown(!showDrowdown);
              }}
            >
              {childrenEl.props.children}
            </li>
          );
        } else {
          console.error("在Select组件中子组件只能使用'Option'");
        }
      });
    };

    const context: ISContext = {};
    return (
      <div className={classes} style={style} ref={componentRef}>
        <Input
          disabled={disabled}
          {...restProp}
          onClick={(e) => {
            setShowDrowdown(!showDrowdown);
          }}
          onKeyDown={keyDown}
          value={selectChild}
        />
        <div className="select-options">
          {selectedOptions &&
            selectedOptions.map((option, index) => {
              return (
                <span className="select-option-item">
                  {option}
                  <Icon
                    icon="times"
                    onClick={(e) => {
                      const arr2 = [...selectedOptions];
                      arr2.splice(index, 1);
                      setSelectedOptions(arr2);
                    }}
                  />
                </span>
              );
            })}
        </div>
        <SelectContext.Provider value={context}>
          {showDrowdown ? (
            <ul className="sailor-suggestion-list">{renderChildren()}</ul>
          ) : (
            ""
          )}
        </SelectContext.Provider>
      </div>
    );
  },
);

export default Select;
